/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tiralabra;

import java.util.*;
import java.lang.Math;
        


/**
 *
 * @author semi
 */
public abstract class Astar {

    private static void katsoRuutu(Ruutu[][] kartta, short X, short Y, short vanhemmanX, short vanhemmanY, short maaliX, short maaliY, int kuljettuMatka, Keko keko) {
        int xEtaisyys = 0;
        int yEtaisyys = 0;
        int manhattanEtaisyys = 0;

        if (kartta[X][Y].onkoKuljettava() && !kartta[X][Y].onkoVierailtu()) {
                // käytetään heuristiikkaa manhattan
                // lasketaan matka
                if (kartta[X][Y].onkoAvoin()) { // avoin tarkoittaa että on keossa eli avoimien listalla
                    if (kuljettuMatka+1 < kartta[X][Y].haeLyhin()) {
                        //jos uusi reitti on lyhyempi kuin aiemmin löydetty
                        kartta[X][Y].asetaAvoimeksi(vanhemmanX, vanhemmanY, kuljettuMatka+1, kuljettuMatka+1+kartta[X][Y].haeArvio()-kartta[X][Y].haeLyhin());
                        KekoAlkio alkio = new KekoAlkio(X, Y);
                        keko.korjaaAlkio(kartta, X, Y, kuljettuMatka+1);
                        //poista vanha keosta, lisää uudelleen
                    }
                } else {

                    xEtaisyys = Math.abs(maaliX-(X));
                    yEtaisyys = Math.abs(maaliY-(Y));
                    manhattanEtaisyys = xEtaisyys + yEtaisyys;
                    kartta[X][Y].asetaAvoimeksi(vanhemmanX, vanhemmanY, kuljettuMatka+1, kuljettuMatka+1+manhattanEtaisyys);
                    KekoAlkio alkio = new KekoAlkio(X, Y);
                    keko.laitaKekoon(kartta, alkio);
                    //laita kekoon
                }
        }
    }

    public static boolean etsiReitti(Ruutu[][] kartta, short lahtoX, short lahtoY, 
            short maaliX, short maaliY, Keko keko, short leveys, short korkeus) {
        short nykX = lahtoX;
        short nykY = lahtoY;
        int kuljettuMatka = 0;
        KekoAlkio alkio;

        while (nykX != maaliX || nykY != maaliY) { /* kun ei olla maalissa */
            // katsotaan oikealle
            Integer temp = nykX+1;
            if (temp < leveys && temp >= 0 ) {
                katsoRuutu(kartta, temp.shortValue(), nykY, nykX, nykY, maaliX, maaliY, kuljettuMatka, keko);
            }
            //katsotaan vasemmalle
            temp = nykX-1;
            if (temp < leveys && temp >= 0 ) {
                katsoRuutu(kartta, temp.shortValue(), nykY, nykX, nykY, maaliX, maaliY, kuljettuMatka, keko);
            }
            //alas
            temp = nykY-1;
            if (temp < korkeus && temp >= 0 ) {
                katsoRuutu(kartta, nykX, temp.shortValue(), nykX, nykY, maaliX, maaliY, kuljettuMatka, keko);
            }
            //ylös
            temp = nykY+1;
            if (temp < korkeus && temp >= 0 ) {
                katsoRuutu(kartta, nykX, temp.shortValue(), nykX, nykY, maaliX, maaliY, kuljettuMatka, keko);
            }
            // kun kaikki käsitelty, merkitään nykX, nykY suljetuksi
            kartta[nykX][nykY].asetaVierailluksi();
            alkio = keko.otaPienin(kartta); /* avoimien listan lyhin */
            if (alkio == null) {
                System.out.println("Keko on tyhjä");
                return false; /* jos keko on tyhjä, ei ole reittiä */
            }
            nykX = alkio.annaX();
            nykY = alkio.annaY();
            kuljettuMatka = kartta[nykX][nykY].haeLyhin();

        }

        System.out.println("Reittimukalöytyi, nykX= "+nykX+" nykY= "+nykY);

        return true;
    }

}
